/*
 * @Description: hash模式路由
 * @version: 
 */
let _Vue = null ;

export default class VueRouter {
  static install (Vue) {
    //1.判断当前插件是否已经安装
    if(VueRouter.install.installed) {
      return 
    } 

    VueRouter.install.installed = true ;

    //2.把Vue构造函数记录到全局变量中,方便在将来在VUE实例方法中使用 vue构造函数，例如，在创建组件时需要调用Vue.component
    _Vue = Vue ;

    //3.把创建vue实例时传入的router对象注入到所有Vue实例上，this.$router就是此时挂载到vue实例上的，且所有组件都是Vue实例
    _Vue.mixin({
      beforeCreate () {
        if (this.$options.router) { //组件没有router属性
          _Vue.prototype.$router = this.$options.router ;
          // this.init() ;
          this.$options.router.init(); 
        }

      }
    })
  }
  constructor (options) {
    this.options = options ;
    this.routerMap =  {};
    this.data = _Vue.observable({
      current: '/'
    }) //data是响应式数据，current 用来存储当前的路由地址，默认情况下是/;
  }

  init () {
    this.createCurrentMap();
    this.initComponents(_Vue) ;
    this.initEvent()
  }

  createCurrentMap () {
    //遍历所有的路由规则，把路由规则解析成键值对的形式，存储到routeMap中
    this.options.routes.forEach(route => {
      this.routerMap[route.path] =  route.component ;
    });
  }

  //创建组件router-link , router-view
  initComponents (Vue) {
    Vue.component('router-link', {
      props:{
        to: String
      } ,
      // h函数的3个参数：
      // 1.选择器，这里用的是标签名
      // 2.标签的属性---attrs:Dom对象的属性
      // 3.生成元素的子元素集合

      render (h) {
        return h('a',{
          attrs: {  
            //这里要注意是attrs，而不是attr!!!
            // attrs：DOM对象的属性

            href: '/#'+this.to
          }
        },[this.$slots.default])
      }
 
      // template: '<a :href="to"><slot></slot></a>'
    }); 
    

    const self = this ;
    Vue.component('router-view', { 
      // 获取当前路由地址对应的组件，
      render (h) {
        console.log('router-view');
        const component = self.routerMap[self.data.current] ;
        return h(component) 
        // h函数会将组件转换成虚拟DOM，最终返回
      }
    })

  }

  initEvent() {
    window.addEventListener('hashchange',()=>{  //监听浏览器地址的变化
      console.log('hashchange',window.location.hash);
      this.data.current = window.location.hash.substr(1) ;
      // data是响应式数据，它的改变会重新加载对应的组件，并将其渲染到视图上； 
    });
  }

}